from typing import Optional, Union, Text, Tuple, List, TypeVar, Sequence
from typing_extensions import Protocol

from pygame.math import Vector2
from pygame.surface import Surface
from pygame.rect import Rect
from pygame.color import Color

_ColorValue = Union[
    Color, Tuple[int, int, int], List[int], int, Tuple[int, int, int, int]
]
_ToSurfaceColorValue = Union[
    Color, Tuple[int, int, int], List[int], int, Text, Tuple[int, int, int, int]
]
_Coordinate = Union[Tuple[float, float], List[float], Vector2]
_CanBeRect = Union[
    Rect,
    Tuple[int, int, int, int], List[int],
    Tuple[_Coordinate, _Coordinate], List[_Coordinate]
]
class _HasRectAttribute(Protocol):
    rect: _CanBeRect
_RectValue = Union[
    _CanBeRect, _HasRectAttribute
]
_Offset = TypeVar("_Offset", Tuple[int, int], Sequence[int])

def from_surface(surface: Surface, threshold: Optional[int] = 127) -> Mask: ...
def from_threshold(
    surface: Surface,
    color: _ColorValue,
    threshold: Optional[_ColorValue] = (0, 0, 0, 255),
    other_surface: Optional[Surface] = None,
    palette_colors: Optional[int] = 1,
) -> Mask: ...

class Mask:
    def __init__(
        self, size: _Coordinate, fill: Optional[bool] = False
    ) -> None: ...
    def copy(self) -> Mask: ...
    def get_size(self) -> Tuple[int, int]: ...
    def get_rect(self, **kwargs) -> Rect: ...  # Dict type needs to be completed
    def get_at(self, pos: _Coordinate) -> int: ...
    def set_at(
        self, pos: _Coordinate, value: Optional[int] = 1
    ) -> None: ...
    def overlap(
        self, other: Mask, offset: _Offset
    ) -> Union[Tuple[int, int], None]: ...
    def overlap_area(self, other: Mask, offset: _Coordinate) -> int: ...
    def overlap_mask(self, other: Mask, offset: _Coordinate) -> Mask: ...
    def fill(self) -> None: ...
    def clear(self) -> None: ...
    def invert(self) -> None: ...
    def scale(self, size: _Coordinate) -> Mask: ...
    def draw(self, other: Mask, offset: _Coordinate) -> None: ...
    def erase(self, other: Mask, offset: _Coordinate) -> None: ...
    def count(self) -> int: ...
    def centroid(self) -> Tuple[int, int]: ...
    def angle(self) -> float: ...
    def outline(self, every: Optional[int] = 1) -> List[Tuple[int, int]]: ...
    def convolve(
        self,
        other: Mask,
        output: Optional[Mask] = None,
        offset: Optional[_Coordinate] = (0, 0),
    ) -> Mask: ...
    def connected_component(
        self, pos: Union[List[int], Tuple[int, int]] = (-1, -1)
    ) -> Mask: ...
    def connected_components(self, minimum: Optional[int] = 0) -> List[Mask]: ...
    def get_bounding_rects(self) -> Rect: ...
    def to_surface(
        self,
        surface: Optional[Surface] = None,
        setsurface: Optional[Surface] = None,
        unsetsurface: Optional[Surface] = None,
        setcolor: Optional[_ToSurfaceColorValue] = (255, 255, 255, 255),
        unsetcolor: Optional[_ToSurfaceColorValue] = (0, 0, 0, 255),
        dest: Optional[Union[_RectValue, _Coordinate]] = (0, 0),
    ) -> Surface: ...
